/*
 * object.cpp
 *
 *  Created on: 21.03.2009
 *      Author: Christian Stupp
 */


#include "../include/object.h"

oal::object::object(std::string newModelName): abstractObject() {
	this->currentPosition = 0;
}

oal::object::object(): abstractObject() {
	this->currentPosition = 0;
}

/*
oal::object & oal::object::operator= (const oal::object &) {
	cout << "Copy" << endl;
	return *this;
}
*/

/**
 * @TODO delete the objects
 *
 */
oal::object::~object() {
//	this->configuration.clear();
	for(int i=0;i<(int)items.size();++i){
		if(items[i] != 0) {
			// cout << "DEL" << items[i] << endl;
			//delete items[i];
			//items[i] = 0;
		}
	}
	this->items.clear();
}


/**
 * Gets the value of the given key from the iterator
 *
 * @param	string	key to search for
 *
 * @return	string	value of given key
 */
std::string oal::object::get(std::string key) {
	return this->values[key].get();
}

/**
 * Sets the given value of the given key in the iterator for future access
 *
 * @param	string	key to set
 * @param	string	value for the key
 */
bool oal::object::set(std::string key, std::string value) {
	this->values[key] = value;
	return true;
}

/**
 * Gets the values of the iterator
 */
oal::array oal::object::getValues(void) {
oal::array result;
string key = "";
	do{
		key = this->values.key();
		string value = this->values[key].get();
		if(value == "Array") {
			result[key] = this->values[key];
		} else {
			result[key] = this->values[key].get();
		}
	} while(this->values.next());
	return result;
}

/**
 * Sets the values of the iterator
 */
void oal::object::setValues(oal::array & newValues) {
string key="";
	do{
		key = newValues.key();
//		cout << "OK" << key << endl;
		string value = newValues[key].get();
		if(value == "Array") {
			this->values[key] = newValues[key];
		} else {
			this->values[key] = value;
		}
	} while(newValues.next());
}

/**
 * Gets the current item from the iterator
 *
 * @return	std::map<std::string, std::string>*	pointer to the map of the iterator
 */
oal::object* oal::object::current() {
	if(this->currentPosition > -1) {
		return items[this->currentPosition];
	}
	return this;
}

/**
 * Appends a model to the iterator
 *
 * @param	*object	model to append
 */
void oal::object::append(object *newObject) {
	this->items.push_back(newObject);
	this->currentPosition = 0;
}

/**
 * Returns true if the iterator has more entrys
 *
 * @return	boolean	true if one more items is avaible,
 * 					false otherwise
 */
bool oal::object::hasNext(void) {
	bool result = false;
	if((int)this->items.size() >= (this->currentPosition+1)) {
		result = true;
	}
	return result;
}

/**
 * Sets the position to the next item in the iterator
 */
void oal::object::next(void) {
	this->currentPosition++;

}

/**
 * Loads a configuration file from the directory configurations/[modelName].conf and
 * add in the iterator of the configuration object for future access.
 *
 * @param	char*	modelName to get configuration
 */
void oal::object::setConfiguration(std::string modelName) {
	std::string filename = (std::string)"configurations/" + modelName + ".conf";
	if(!this->isFile(filename)) {
		filename = (std::string)"../configurations/" + modelName + ".conf";
	}
	if(!this->isFile(filename)) {
		filename = (std::string)"../../configurations/" + modelName + ".conf";
	}
	if(!this->isFile(filename)) {
		filename = (std::string)"res/configuration_" + modelName + ".conf";
	}
	this->putConfigurationContentIntoObject(
		this->loadFromFile(filename)
	);
}

/**
 * Loads the configuration file into the object. this can acccess over
 * the static variable configuration it is a string,string map
 * use configuration[key] to get the value
 *
 * @param	string	path to configuration
 * @param	string	linebreak default is \n
 * @param	string	seperator default is :
 *
 * @return	bool	true if configuration is loaded,
 * 					false otherwise
 */
bool oal::object::parseConfiguration(std::string fileName, std::string linebreak,std::string seperator) {
	files *file = new files(fileName,"r");
	bool result = false;
	if(file->isFile()) {
		std::string content = file->getContent();
		int pos = -1, lastPos = 0;
		while( (pos = content.find(linebreak, pos+1)) > -1) {
			std::string line = content.substr(lastPos, (pos - lastPos));
			int pos2 = line.find(seperator);
			if(pos2>1 && line[0] != '#') {
				this->configuration[trim(line.substr(0,pos2))] = trim(line.substr(pos2+1));
			}
			lastPos = pos+1;
			result = true;
		}
	}
	delete file;
	return result;
}
/**
 * Puts the Configration Files into the Object
 *
 * @param	string	content to set for
 */
void oal::object::putConfigurationContentIntoObject(std::string content) {
	int pos = -1, last = 0;
	this->eraseComments(&content);
	while ( (pos = content.find("\n",pos+1)) > -1 ) {
		std::string line = "";
		line= content.substr(last,pos-last);
		int pos2 = line.find(":");
		if(pos2 > -1) {
			this->configuration[(trim(line.substr(0,pos2)))] = trim(line.substr(pos2+1));
		}
		last = pos;
	}
}

/**
 * Erase all comments form content with comments falgs enclosed and
 * with double slash behind
 *
 * @param	string	content to erase comments
 *
 * @return	string	clean content without comments
 */
void oal::object::eraseComments(std::string *content) {
	int pos = 0;
	// erase all comments with /* */ and #
	while ( (pos = (*content).find("/*",pos)) > -1 ) {
		int pos2 = (*content).find("*/",pos);
		(*content) = (*content).replace(pos,(pos2-pos)+2,"");
	}
	pos = 0;
	while ( (pos = (*content).find("#",pos)) > -1 ) {
		int pos2 = (*content).find("\n",pos);
		(*content) = (*content).replace(pos,(pos2-pos)+1,"");
	}

}


//////////////////////////////////////////////////////////////////////////////////////////
// Start Helper Function for all models and controller and views
//////////////////////////////////////////////////////////////////////////////////////////

/**
 * Checks if the filename exists on the diskspace
 *
 * @param	string	filename to check
 *
 * @return	boolean	true if the file is exists,
 * 					false otherwise.
 */
bool oal::object::isFile(std::string fileName) {
	bool result="";
	files *file = new files(fileName,"");
	result = file->isFile();
	delete file;
	return result;
}

/**
 * Deletes a file from the disk
 *
 * @param	string	filename to delete
 *
 * @return	boolean	true if successful deletes,
 * 					otherwise false
 */
bool oal::object::deleteFile(std::string fileName) {
	bool result=false;
	files *file = new files(fileName,"");
	result = file->erase();
	delete file;
	return result;
}

/**
 * Gets the content from stdin
 *
 * @return	string	content from stdin
 */
std::string oal::object::loadContentFromStdin(void) {
	std::string result="";
	files *file = new files();
	result = file->getFromStdin();
	free(file);
	return result;
}


/**
 * Search for the given name in the iterator and returns his id
 *
 * @param	string	key to search for
 * @param	string	name to search with the given key
 *
 * @return	integer	id of the found record, otherwise returns -1
 */
int oal::object::getIdByName(std::string name, std::string value) {
	std::vector< object* >::iterator	vectorIter;
	int id = -1;
	int pos = 0;
	for(
			vectorIter = this->items.begin();
			vectorIter != this->items.end();
			++vectorIter
	) {
		if((*vectorIter)->values[name].get() == value) {
			id = pos;
		}
		pos++;
	}
	return id;
}

/**
 * Prints the iterator data from the values
 *
 * @param	string	methodname valid are xml , array
 *
 * @return string data from values
 */
std::string oal::object::printIteratorData(
		std::string type,
		oal::array* values,
		string tabLevel) {
	std::string result="";
	std::map<std::string, std::string>::iterator	mapIter;
	do{
		string key = (*values).key();
		if(type == "array") {
			result += tabLevel + "  [" + key + "] = " + (*values)[key].get() + "\n";
		} else {
			result += tabLevel + "  <" + key + ">" + (*values)[key].get()+ "</" + key + ">\n";
		}
	} while((*values).next());

	return result;
}
/**
 * Gets the content of the model iterator an different methods
 *
 * @param	string	methodname valid are xml , array
 *
 * @return	string	data from values and iterator
 */
std::string oal::object::getIteratorData(std::string  type,string  tabLevel) {
	std::string result="";
	std::vector< object* >::iterator	vectorIter;
	std::map<std::string, std::string>::iterator	mapIter;

	tabLevel += "  ";
	result = tabLevel + "[object]\n" +
		this->printIteratorData(type, &this->values, tabLevel);

	for(int i=0;i<(int)this->items.size();++i) {
		result += tabLevel + "  [object]\n";
		result += this->printIteratorData(type, &this->items[i]->values, tabLevel + "  ");
		result += tabLevel + "  [object]\n";
	}
	result +=  tabLevel + "[object]\n";
	return result;
}

/**
 * Debugs the current iterator
 */
std::string oal::object::debugIt(void) {
	return "[DEBUG]\n" + this->getIteratorData("array") + "[/DEBUG]\n";
}

/**
 * Gets an XML output from the model iterator
 */
std::string oal::object::getXmlContent(void) {
	std::string result="";
	result = "<?xml version=\"1.0\"?>\n<root>\n";
	result += this->getIteratorData("xml");
	result += "</root>\n";
	return result;
}
